﻿using Admin.NET.Core.Service;
using Admin.NET.Application.Const;
using Admin.NET.Application.Entity;
using Microsoft.AspNetCore.Http;
using System.Linq;
using Magicodes.ExporterAndImporter.Excel;
using System.IO;
using Furion.DatabaseAccessor;
using Magicodes.ExporterAndImporter.Core;
namespace Admin.NET.Application;
/// <summary>
/// 考生服务
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class KaoshengService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<Kaosheng> _rep;
    private readonly SqlSugarRepository<Student> _studentRep;
    private readonly SqlSugarRepository<Banji> _banjiRep;
    private readonly SqlSugarRepository<JiaoxueBan> _jiaoxueBanRep;
    private readonly SqlSugarRepository<Shichang> _shichangRep;
    private readonly SqlSugarRepository<Kaoshi> _kaoshiRep;
    private readonly SqlSugarRepository<SysFile> _fileRep;

    public KaoshengService(SqlSugarRepository<Kaosheng> rep, SqlSugarRepository<Student> studentRep, SqlSugarRepository<Shichang> shichangRep, SqlSugarRepository<Kaoshi> kaoshiRep, SqlSugarRepository<SysFile> fileRep, SqlSugarRepository<Banji> banjiRep, SqlSugarRepository<JiaoxueBan> jiaoxueBanRep)
    {
        _rep = rep;
        _studentRep = studentRep;
        _shichangRep = shichangRep;
        _kaoshiRep = kaoshiRep;
        _fileRep = fileRep;
        _banjiRep = banjiRep;
        _jiaoxueBanRep = jiaoxueBanRep;
    }

    /// <summary>
    /// 分页查询考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    public async Task<SqlSugarPagedList<KaoshengOutput>> Page(KaoshengInput input)
    {
        var query = _rep.AsQueryable()
            //处理外键和TreeSelector相关字段的连接
            .LeftJoin<Kaoshi>((u, kaoshiid) => u.KaoshiId == kaoshiid.Id)
            .LeftJoin<Banji>((u, kaoshiid, banjiid) => u.BanjiId == banjiid.Id)
            .LeftJoin<Student>((u, kaoshiid, banjiid, studentid) => u.StudentId == studentid.Id)
            .LeftJoin<JiaoxueBan>((u, kaoshiid, banjiid, studentid,jiaoxueBanid) => u.JiaoxueBanId == jiaoxueBanid.Id)
            .Where((u, kaoshiid, banjiid, studentid, jiaoxueBanid) => studentid.BeAtSchool == true)
            .WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), (u, kaoshiid, banjiid, studentid) =>
                studentid.Xh.Contains(input.SearchKey.Trim())
                || studentid.Name.Contains(input.SearchKey.Trim())
                || u.ShiChangNum.Contains(input.SearchKey.Trim())
                || u.ZuoweiHao.Contains(input.SearchKey.Trim())
                || u.ZhunkaoZhenghao.Contains(input.SearchKey.Trim())
                || banjiid.Name.Contains(input.SearchKey.Trim())
            )
            .WhereIF(input.KaoshiId>0, u => u.KaoshiId == input.KaoshiId)
            .WhereIF(input.BanjiId>0, u => u.BanjiId == input.BanjiId)
            .WhereIF(input.StudentId>0, u => u.StudentId == input.StudentId)
            .WhereIF(input.KaoHao>0, u => u.KaoHao == input.KaoHao)
            .WhereIF(!string.IsNullOrWhiteSpace(input.ShiChangNum), u => u.ShiChangNum.Contains(input.ShiChangNum.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.ZuoweiHao), u => u.ZuoweiHao.Contains(input.ZuoweiHao.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.ZhunkaoZhenghao), u => u.ZhunkaoZhenghao.Contains(input.ZhunkaoZhenghao.Trim()))
            .WhereIF(input.BanjiMC>0, u => u.BanjiMC == input.BanjiMC)
            .WhereIF(input.JiMC>0, u => u.JiMC == input.JiMC)
            .OrderBy(u => u.KaoHao)
            .Select((u, kaoshiid, banjiid, studentid, jiaoxueBanid) => new KaoshengOutput
            {
                Id = u.Id,
                KaoshiId = u.KaoshiId, 
                KaoshiIdName = kaoshiid.Name,
                BanjiId = u.BanjiId, 
                BanjiIdName = banjiid.Name,
                JiaoxueBanId= u.JiaoxueBanId,
                JiaoxueBanIdName = jiaoxueBanid.Name,
                StudentId = u.StudentId, 
                StudentIdName = studentid.Name,
                StudentIdXh = studentid.Xh,
                AssistNum = studentid.AssistNum,
                Sex = studentid.Sex,
                KaoHao = u.KaoHao,
                ShiChangNum = u.ShiChangNum,
                ZuoweiHao = u.ZuoweiHao,
                ZhunkaoZhenghao = u.ZhunkaoZhenghao,
                Active = u.Active,
                ZongFen = u.ZongFen,
                BanjiMC = u.BanjiMC,
                JiMC = u.JiMC,
                CreateUserName = u.CreateUserName,
                UpdateUserName = u.UpdateUserName,
            });
        return await query.ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 增加考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    public async Task<long> Add(AddKaoshengInput input)
    {
        var entity = input.Adapt<Kaosheng>();
        await _rep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    public async Task Delete(DeleteKaoshengInput input)
    {
        var entity = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        await _rep.FakeDeleteAsync(entity);   //假删除
        //await _rep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 更新考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    public async Task Update(UpdateKaoshengInput input)
    {
        var entity = input.Adapt<Kaosheng>();
        await _rep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    public async Task<Kaosheng> Detail([FromQuery] QueryByIdKaoshengInput input)
    {
        return await _rep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取考生列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    public async Task<List<KaoshengOutput>> List([FromQuery] KaoshengInput input)
    {
        return await _rep.AsQueryable().Select<KaoshengOutput>().ToListAsync();
    }

    /// <summary>
    /// 获取考试列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "KaoshiKaoshiIdDropdown"), HttpGet]
    public async Task<dynamic> KaoshiKaoshiIdDropdown()
    {
        return await _rep.Context.Queryable<Kaoshi>()
                .Select(u => new
                {
                    Label = u.Name,
                    Value = u.Id
                }
                ).ToListAsync();
    }
    /// <summary>
    /// 获取班级列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "BanjiBanjiIdDropdown"), HttpGet]
    public async Task<dynamic> BanjiBanjiIdDropdown()
    {
        return await _rep.Context.Queryable<Banji>()
                .Select(u => new
                {
                    Label = u.Name,
                    Value = u.Id
                }
                ).ToListAsync();
    }

    /// <summary>
    /// 获取教学班表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "JiaoxueBanJiaoxueBanIdDropdown"), HttpGet]
    public async Task<dynamic> JiaoxueBanJiaoxueBanIdDropdown()
    {
        return await _rep.Context.Queryable<JiaoxueBan>()
                .Select(u => new
                {
                    Label = u.Name,
                    Value = u.Id
                }
                ).ToListAsync();
    }

    /// <summary>
    /// 获取学生列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "StudentStudentIdDropdown"), HttpGet]
    public async Task<dynamic> StudentStudentIdDropdown()
    {
        return await _rep.Context.Queryable<Student>()
                .Select(u => new
                {
                    Label = u.Xh + u.Name,
                    Value = u.Id
                }
                ).ToListAsync();
    }

    /// <summary>
    /// 从学生库导入考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "ImportFromStudent")]
    public async Task ImportFromStudent(ImportFromStudentInput input)
    {
        foreach (long id in input.StudentIds)
        {
            var student = _studentRep.GetById(id);
            var kaosheng = new Kaosheng
            {
                KaoshiId = input.KaoshiId,
                BanjiId = student.BanjiId,
                JiaoxueBanId = student.JiaoxueBanId,
                StudentId = id,
                Active=true
            };
            await _rep.InsertAsync(kaosheng);
        }
    }

    /// <summary>
    /// 从学生库导入考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "BatchDelete")]
    public async Task BatchDelete(List<long> input)
    {
        foreach (long id in input)
        {
            await _rep.DeleteByIdAsync(id);
        }
    }

    /// <summary>
    /// 随机生成考号
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "RandomKaohao")]
    public async Task RandomKaohao(KaoshengKaoshiIdInput input)
    {
        var cnt = await _rep.AsQueryable().CountAsync(p=>p.KaoshiId == input.KaoshiId);
        var list = await _rep.AsQueryable().Where(p=>p.KaoshiId == input.KaoshiId).ToListAsync();
        Random random = new Random();
        foreach (var item in list)
        {
            int randomInt = random.Next(1, cnt + 1);
            item.KaoHao = randomInt;
        }
        list = list.OrderBy(p=>p.KaoHao).ToList();
        int kaohao = 1;
        foreach (var item in list)
        {
            item.KaoHao = kaohao++;
            await _rep.UpdateAsync(item);
        }
    }

    /// <summary>
    /// 生成试场号座位号
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "SetShichangNumZuoweihao")]
    public async Task SetShichangNumZuoweihao(KaoshengKaoshiIdInput input)
    {
        var list = await _rep.AsQueryable().Where(p => p.KaoshiId == input.KaoshiId).ToListAsync();
        list = list.OrderBy(p => p.KaoHao).ToList();
        var shichangs = await _shichangRep.AsQueryable().Where(p => p.KaoshiId == input.KaoshiId).ToListAsync();
        int sum = 0;
        foreach (var item in shichangs)
        {
            sum += item.Renshu;
        }
        if(sum != list.Count)
        {
            throw Oops.Oh("考生人数跟试场设置的人数不一致！");
        }
        var index = 0;
        foreach (var shichang in shichangs)
        {
            if (index >= list.Count)
            {
                break;
            }
            for (int i = 1; i <= shichang.Renshu; i++)
            {
                if (index >= list.Count)
                {
                    break;
                }
                list[index].ShiChangNum = shichang.ShiChangNum;
                list[index].ZuoweiHao = i.ToString().PadLeft(2,'0');
                await _rep.UpdateAsync(list[index]);
                index++;
            }
        }
    }

    /// <summary>
    /// 生成试场号座位号
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "SetZhunkaozhenghao")]
    public async Task SetZhunkaozhenghao(KaoshengKaoshiIdInput input)
    {
        var kaoshi = await _kaoshiRep.GetByIdAsync(input.KaoshiId);

        var list = await _rep.AsQueryable().Where(p => p.KaoshiId == input.KaoshiId).ToListAsync();
        list = list.OrderBy(p => p.KaoHao).ToList();
        foreach (var item in list)
        {
            item.ZhunkaoZhenghao = kaoshi.PerNum + item.KaoHao.ToString().PadLeft(4, '0');
            await _rep.UpdateAsync(item);
        }
    }

    /// <summary>
    /// 清空考生
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "clear")]
    public async Task Clear(KaoshengKaoshiIdInput input)
    {
        await _rep.AsDeleteable().Where(p=>p.KaoshiId == input.KaoshiId).ExecuteCommandAsync();
    }

    /// <summary>
    /// 导出考生for云阅卷
    /// </summary>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Export"), NonUnify]
    [DisplayName("导出")]
    public async Task<IActionResult> Export(KaoshengKaoshiIdInput input)
    {
        var list = await _rep.AsQueryable()
            .LeftJoin<Student>((kaosheng,student) => kaosheng.StudentId == student.Id)
            .LeftJoin<Banji>((kaosheng,student,banji) => kaosheng.BanjiId == banji.Id)
            .LeftJoin<JiaoxueBan>((kaosheng,student,banji,jiaoxueBan) => kaosheng.JiaoxueBanId == jiaoxueBan.Id)
            .Where(kaosheng => kaosheng.KaoshiId == input.KaoshiId)
            .OrderBy(kaosheng => kaosheng.KaoHao, OrderByType.Asc)
            .Select((kaosheng, student, banji,jiaoxueBan) => new ExportKaoshengDto
            {
                BanjiIdName = banji.Name,
                JiaoxueBanIdName = jiaoxueBan.Name,
                StudentIdName = student.Name,
                StudentIdXh = student.Xh,
                Sex = student.Sex,
                KaoHao = kaosheng.KaoHao,
                ShiChangNum = kaosheng.ShiChangNum,
                ZuoweiHao = kaosheng.ZuoweiHao,
                ZhunkaoZhenghao = kaosheng.ZhunkaoZhenghao,
                Active = kaosheng.Active,
                AssistNum = student.AssistNum,         
            }).ToListAsync();
        foreach (var item in list)
        {
            var shichang = await _shichangRep.AsQueryable().Where(p=>p.KaoshiId == input.KaoshiId && p.ShiChangNum == item.ShiChangNum).FirstAsync();
            if(shichang != null)
            {
                item.Address1 = shichang.Address1;
                item.Address2 = shichang.Address2;
            }
        }

        var kaoshi =await _kaoshiRep.GetByIdAsync(input.KaoshiId);

        IExcelExporter excelExporter = new ExcelExporter();
        var res = await excelExporter.ExportAsByteArray(list);
        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + kaoshi.Name + "考生.xlsx" };
    }

    /// <summary>
    /// 导出考生for云阅卷
    /// </summary>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "ExportForXiwo"), NonUnify]
    [DisplayName("导出")]
    public async Task<IActionResult> ExportForXiwo(KaoshengKaoshiIdInput input)
    {
        var list = await _rep.AsQueryable()
            .LeftJoin<Student>((kaosheng, student) => kaosheng.StudentId == student.Id)
            .LeftJoin<Banji>((kaosheng, student, banji) => kaosheng.BanjiId == banji.Id)
            .Where(kaosheng => kaosheng.KaoshiId == input.KaoshiId)
            .OrderBy(kaosheng => kaosheng.KaoHao, OrderByType.Asc)
            .Select((kaosheng, student, banji) => new ExportKaoshengForXiwoDto
            {
                StudentIdName = student.Name,
                StudentIdXh = student.Xh,
                ZuoweiHao = kaosheng.ZuoweiHao,
                ZhunkaoZhenghao = kaosheng.ZhunkaoZhenghao,
                ShiChangNum = kaosheng.ShiChangNum,
            }).ToListAsync();
        for (int i = 0; i < list.Count; i++)
        {
            var shichang = await _shichangRep.AsQueryable().Where(p => p.KaoshiId == input.KaoshiId && p.ShiChangNum == list[i].ShiChangNum).FirstAsync();
            list[i].Address2 = shichang.Address2;
        }

        IExcelExporter excelExporter = new ExcelExporter();
        var res = await excelExporter.ExportAsByteArray(list);
        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "考生批量导入模板.xlsx" };
    }

    /// <summary>
    /// 考生导入
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "Import")]
    public async Task<string> Import(ImportKaoshengInput input)
    {
        var file = _fileRep.GetById(input.fileId);
        var filePath = App.WebHostEnvironment.WebRootPath;
        filePath = System.IO.Path.Combine(filePath, file.FilePath);
        filePath = System.IO.Path.Combine(filePath, file.Id.ToString());
        filePath += file.Suffix;

        IImporter importer = new ExcelImporter();
        var res = await importer.Import<ImportKaoshengDto>(filePath);
        foreach (var item in res.Data)
        {
            Kaosheng kaosheng;
            Student student;
            var banji = await _banjiRep.AsQueryable().FirstAsync(p => p.Name == item.BanjiIdName);
            var JiaoxueBan = await _jiaoxueBanRep.AsQueryable().FirstAsync(p => p.Name == item.JiaoxueBanIdName);
            if (item.StudentIdXh != null)
            {
                student =await _studentRep.AsQueryable().Where(p => p.Xh == item.StudentIdXh).FirstAsync();
                if (student == null)
                {
                    throw Oops.Oh(item.StudentIdName + "学生不存在");
                }
                kaosheng = await _rep.AsQueryable().Where(p=>p.KaoshiId == input.KaoshiId && p.StudentId == student.Id).FirstAsync();
                
            }
            else
            {
                if(item.AssistNum != null)
                {
                    student = await _studentRep.AsQueryable().Where(p => p.AssistNum == item.AssistNum).FirstAsync();
                }
                else
                {
                    student = await _studentRep.AsQueryable().Where(p => p.BanjiId == banji.Id && p.Name == item.StudentIdName).FirstAsync();
                }
                if (student == null)
                {
                    throw Oops.Oh(item.StudentIdName + "学生不存在");
                }
                kaosheng = await _rep.AsQueryable().Where(p => p.KaoshiId == input.KaoshiId && p.StudentId == student.Id).FirstAsync();
            }
            if (kaosheng == null)
            {
                kaosheng = new Kaosheng();
                kaosheng.KaoshiId = input.KaoshiId;
                kaosheng.StudentId = student.Id;
                if (banji != null)
                    kaosheng.BanjiId = banji.Id;
                else
                    kaosheng.BanjiId = student.BanjiId;
                if (JiaoxueBan != null)
                {
                    kaosheng.JiaoxueBanId = JiaoxueBan.Id;
                }
                else
                {
                    kaosheng.JiaoxueBanId = student.JiaoxueBanId;
                }
            }
            kaosheng.KaoHao = item.KaoHao;
            kaosheng.ShiChangNum = item.ShiChangNum;
            kaosheng.ZuoweiHao = item.ZuoweiHao;
            kaosheng.ZhunkaoZhenghao = item.ZhunkaoZhenghao;
            kaosheng.Active = item.Active != "否";
            if (kaosheng.Id == 0)
            {
                await _rep.InsertAsync(kaosheng);
            }
            else
            {
                await _rep.UpdateAsync(kaosheng);
            }
        }
        return string.Format("成功导入{0}条记录", res.Data.Count);
    }
}

